package com.client.elements.normal;

import java.util.ArrayList;

import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.Widget;

public class Dreigewinnt_KI {

	static Boolean fertig;

	static FlowPanel panel = new FlowPanel();
	static HorizontalPanel row_top = new HorizontalPanel();
	static Label top_first = new Label();
	static Label top_second = new Label();
	static Label top_third = new Label();
	static HorizontalPanel row_middle = new HorizontalPanel();
	static Label middle_first = new Label();
	static Label middle_second = new Label();
	static Label middle_third = new Label();
	static HorizontalPanel row_bottom = new HorizontalPanel();
	static Label bottom_first = new Label();
	static Label bottom_second = new Label();
	static Label bottom_third = new Label();

	static ArrayList<Label> labels = new ArrayList<Label>();

	static ClickHandler clearer = new ClickHandler() {
		@Override
		public void onClick(ClickEvent event) {
			for (int i = 0; i < labels.size(); i++) {
				labels.get(i).setText("");
				labels.get(i).removeStyleName("red_Background");
			}
			fertig = false;
		}
	};

	static Button clear = new Button("Clear", clearer);

	public static Widget dreigewinnt(){
		fertig = false;

		labels.clear();
		row_top.clear();
		row_middle.clear();
		row_bottom.clear();
		panel.clear();

		labels.add(top_first);
		labels.add(top_second);
		labels.add(top_third);
		labels.add(middle_first);
		labels.add(middle_second);
		labels.add(middle_third);
		labels.add(bottom_first);
		labels.add(bottom_second);
		labels.add(bottom_third);

		for (int i = 0; i < labels.size(); i++) {
			labels.get(i).setText("");
			labels.get(i).getElement().setId(i + "");
			labels.get(i).addStyleName("label_dg");
			labels.get(i).addClickHandler(clicker);
			if (i>5) row_bottom.add(labels.get(i));
			else if (i<3) row_top.add(labels.get(i));
			else row_middle.add(labels.get(i));
		}

		panel.add(row_top);
		panel.add(row_middle);
		panel.add(row_bottom);
		panel.add(clear);
		return panel;
	}

	static ClickHandler clicker = new ClickHandler() {
		@Override
		public void onClick(ClickEvent event) {
			if (!fertig) {
				if (event.getRelativeElement().getInnerText().equals("")) {
					String user = "X";
					event.getRelativeElement().setInnerText(user);

					if (ueberpruefeGewinn()) {
						Window.alert("Mensch hat gewonnen.");
						fertig = true;
					}
					ueberpruefeFertig();

					if (!fertig) {
						ki();
						if (ueberpruefeGewinn()) {
							Window.alert("Computer hat gewonnen.");
							fertig = true;
						}
					}
					ueberpruefeFertig();
				}
			}
		}
	};

	public static boolean ki(){
		{//wenn sich die Gelegenheit ergibt, wird eine Reihe vervollständigt.
			//-->horizontal
			for (int zeile = 0; zeile < 3; zeile++) {
				int ergebnis = 0;
				for (int eintrag = 3*zeile; eintrag < (3 + zeile*3); eintrag++ ) {
					ergebnis = ergebnis + userEingabeAuswertung(eintrag);
				}
				if (ergebnis == 2) {
					for (int eintrag = 3*zeile; eintrag < (3 + zeile*3); eintrag++ ) {
						labels.get(eintrag).setText("O");
					}
					return true;
				}
			}

			//-->vertikal
			for (int spalte = 0; spalte < 3; spalte++) {
				int ergebnis = 0;
				for (int eintrag = spalte; eintrag < (7 + spalte); eintrag = eintrag + 3) {
					ergebnis = ergebnis + userEingabeAuswertung(eintrag);
				}
				if (ergebnis == 2) {
					for (int eintrag = spalte; eintrag < (7 + spalte); eintrag = eintrag + 3) {
						labels.get(eintrag).setText("O");
					}
					return true;
				}
			}

			//-->diagonal
			for (int richtung = 0; richtung < 2; richtung++) {
				int ergebnis = 0;
				for (int eintrag = 2*richtung; eintrag < (9 - 2*richtung); eintrag = eintrag + 4 - 2 * richtung) {
					ergebnis = ergebnis + userEingabeAuswertung(eintrag);
				}
				if (ergebnis == 2) {
					for (int eintrag = 2*richtung; eintrag < (9 - 2*richtung); eintrag = eintrag + 4 - 2 * richtung) {
						labels.get(eintrag).setText("O");
					}
					return true;
				}
			}
		}

		{//Wenn keine Reihe gemacht werden kann, wird eine Reihe des Gegners unterbrochen.
			for (int zeile = 0; zeile < 3; zeile++) {
				int ergebnis = 0;
				for (int eintrag = 3*zeile; eintrag < (3 + zeile*3); eintrag++ ) {
					ergebnis = ergebnis + userEingabeAuswertung(eintrag);
				}
				if (ergebnis == -2) {
					for (int eintrag = 3*zeile; eintrag < (3 + zeile*3); eintrag++ ) {
						if (labels.get(eintrag).getText().equals("")) {
							labels.get(eintrag).setText("O");
							return true;
						}
					}
				}
			}

			//-->vertikal
			for (int spalte = 0; spalte < 3; spalte++) {
				int ergebnis = 0;
				for (int eintrag = spalte; eintrag < (7 + spalte); eintrag = eintrag + 3) {
					ergebnis = ergebnis + userEingabeAuswertung(eintrag);
				}
				if (ergebnis == -2) {
					for (int eintrag = spalte; eintrag < (7 + spalte); eintrag = eintrag + 3) {
						if (labels.get(eintrag).getText().equals("")) {
							labels.get(eintrag).setText("O");
							return true;
						}				
					}			
				}
			}

			//-->diagonal
			for (int richtung = 0; richtung < 2; richtung++) {
				int ergebnis = 0;
				for (int eintrag = 2*richtung; eintrag < (9 - 2*richtung); eintrag = eintrag + 4 - 2 * richtung) {
					ergebnis = ergebnis + userEingabeAuswertung(eintrag);
				}
				if (ergebnis == -2) {
					for (int eintrag = 2*richtung; eintrag < (9 - 2*richtung); eintrag = eintrag + 4 - 2 * richtung) {
						if (labels.get(eintrag).getText().equals("")) {
							labels.get(eintrag).setText("O");
							return true;
						}		
					}
				}
			}
		}

		{//Trick mit Ecken
			for (int i = 1; i < 8; i = i + 6) {
				for (int j = 3; j < 6; j = j + 2) {
					if (labels.get(i).getText().equals(labels.get(j).getText()) && labels.get(i).getText().equals("X")) {
						if (labels.get(i + j - 4).getText().equals("")) {
							labels.get(i + j - 4).setText("O");
							return true;
						}
					}
				}
			}
		}

		{//Es wird eine Reihe, in der nur ein Feld vom Computer ausgefuellt ist, erweitert

			//Wenn 2 gegenseitige Ecken ausgewaehlt wurden, darf keine andere Ecke ausgewaehlt werden
			int anzahl_ausgefuellt = 0;
			for (int i = 0; i < labels.size(); i++) {
				if (labels.get(i).getText().equals("") == false) {
					anzahl_ausgefuellt++;
				}
			}
			Boolean ecken = true;
			if (anzahl_ausgefuellt == 3) {
				if (labels.get(0).getText().equals("X") && labels.get(8).getText().equals("X")) {
					ecken = false;
				}
				if (labels.get(2).getText().equals("X") && labels.get(6).getText().equals("X")) {
					ecken = false;
				}
			}

			//-->horizontal
			ArrayList<Label> labels_potentiell = new ArrayList<Label>();
			for (int zeile = 0; zeile < 3; zeile++) {
				int ergebnis = 0;
				for (int eintrag = 3*zeile; eintrag < (3 + zeile*3); eintrag++ ) {
					ergebnis = ergebnis + userEingabeAuswertung(eintrag);
				}
				if (ergebnis == 1) {
					for (int eintrag = 3*zeile; eintrag < (3 + zeile*3); eintrag++ ) {
						if (labels.get(eintrag).getText().equals("")) {
							labels_potentiell.add(labels.get(eintrag));
						}
					}
				}
			}

			//-->vertikal
			for (int spalte = 0; spalte < 3; spalte++) {
				int ergebnis = 0;
				for (int eintrag = spalte; eintrag < (7 + spalte); eintrag = eintrag + 3) {
					ergebnis = ergebnis + userEingabeAuswertung(eintrag);
				}
				if (ergebnis == 1) {
					for (int eintrag = spalte; eintrag < (7 + spalte); eintrag = eintrag + 3) {
						if (labels.get(eintrag).getText().equals("")) {
							labels_potentiell.add(labels.get(eintrag));
						}			
					}
				}
			}

			//-->diagonal
			for (int richtung = 0; richtung < 2; richtung++) {
				int ergebnis = 0;
				for (int eintrag = 2*richtung; eintrag < (9 - 2*richtung); eintrag = eintrag + 4 - 2 * richtung) {
					ergebnis = ergebnis + userEingabeAuswertung(eintrag);
				}
				if (ergebnis == 1) {
					for (int eintrag = 2*richtung; eintrag < (9 - 2*richtung); eintrag = eintrag + 4 - 2 * richtung) {
						if (labels.get(eintrag).getText().equals("")) {
							labels_potentiell.add(labels.get(eintrag));
						}
					}
				}
			}
			if (labels_potentiell.size()>0) {
				if (!ecken) {
					for (int i = 0; i < labels_potentiell.size(); i++) {
						int id = Integer.parseInt(labels_potentiell.get(i).getElement().getId());
						if ((id==0) ||(id==2) ||(id==6) ||(id==8)) {
							labels_potentiell.remove(i);
							i--;
						}
					}
				}
				labels_potentiell.get((int)(labels_potentiell.size()*Math.random())).setText("O");
				return true;
			}
		}

		{//Als erster Schritt wird, sofern moeglich, die Mitte ausgewaehlt.
			if (labels.get(4).getText().equals("")) {
				labels.get(4).setText("O");
				return true;
			}else {
				ArrayList<Label> x = new ArrayList<Label>();
				for (int i = 0; i < 2; i++) {
					for (int j = 0 + i*6; j < labels.size(); j = j + 2) {
						if (labels.get(j).getText().equals("")) {
							x.add(labels.get(j));
						}
					}
				}
				if (x.size() != 0) {
					x.get((int)((x.size()*Math.random()))).setText("O");
					return true;
				}
			}
		}

		{//Ansonsten wird ein zufalliges leeres Feld ausgewaehlt.
			ArrayList<Label> unbelegt = new ArrayList<Label>();
			for (int i = 0; i < labels.size(); i++) {
				if (labels.get(i).getText().equals("")) {
					unbelegt.add(labels.get(i));
				}
			}
			int rd = (int)(Math.random()*unbelegt.size());
			unbelegt.get(rd).setText("O");
			return true;
		}
	}

	static int userEingabeAuswertung(int i ){
		if (labels.get(i).getText().equals("O")) {
			return 1;
		}else if(labels.get(i).getText().equals("X")){
			return -1;
		}else {
			return 0;
		}
	}

	public static Boolean ueberpruefeGewinn(){
		//-->horizontal
		for (int zeile = 0; zeile < 3; zeile++) {
			int ergebnis = 0;
			for (int eintrag = 3*zeile; eintrag < (3 + zeile*3); eintrag++ ) {
				ergebnis = ergebnis + userEingabeAuswertung(eintrag);
				if (ergebnis == 3 || ergebnis == -3) {
					for (int eintrag_2 = 3*zeile; eintrag_2 < (3 + zeile*3); eintrag_2++ ) {
						labels.get(eintrag_2).addStyleName("red_Background");
					}
					return true;
				}
			}
		}

		//-->vertikal
		for (int spalte = 0; spalte < 3; spalte++) {
			int ergebnis = 0;
			for (int eintrag = spalte; eintrag < (7 + spalte); eintrag = eintrag + 3) {
				ergebnis = ergebnis + userEingabeAuswertung(eintrag);
				if (ergebnis == 3 || ergebnis == -3) {
					for (int eintrag_2 = spalte; eintrag_2 < (7 + spalte); eintrag_2 = eintrag_2 + 3) {
						labels.get(eintrag_2).addStyleName("red_Background");
					}
					return true;
				}
			}
		}

		//-->diagonal
		for (int richtung = 0; richtung < 2; richtung++) {
			int ergebnis = 0;
			for (int eintrag = 2*richtung; eintrag < (9 - 2*richtung); eintrag = eintrag + 4 - 2 * richtung) {
				ergebnis = ergebnis + userEingabeAuswertung(eintrag);
				if (ergebnis == 3 || ergebnis == -3) {
					for (int eintrag_2 = 2*richtung; eintrag_2 < (9 - 2*richtung); eintrag_2 = eintrag_2 + 4 - 2 * richtung) {
						labels.get(eintrag_2).addStyleName("red_Background");
					}
					return true;
				}
			}
		}
		return false;
	}

	static void ueberpruefeFertig(){
		Boolean alleVoll = true;
		for (int i = 0; i < labels.size(); i++) {
			if (labels.get(i).getText().equals("") ) {
				alleVoll = false;
			}
		}
		if (alleVoll && !fertig) {
			Window.alert("Unentschieden");
			fertig = true;
		}
	}
}